import sys
import os
import json
import base64
import webbrowser
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem,
    QPushButton, QLineEdit, QLabel, QMessageBox, QDialog, QFormLayout, QDialogButtonBox, QInputDialog, QHeaderView
)
from PyQt5.QtCore import Qt, QEvent, QTimer
from PyQt5.QtGui import QFont, QColor, QCursor

DATA_FILE = 'passwords.enc'

class EntryDialog(QDialog):
    def __init__(self, parent=None, entry=None):
        super().__init__(parent)
        self.setWindowTitle('条目信息')
        self.setFixedSize(500, 400)
        self.setStyleSheet('QDialog { background: #fff; border-radius: 16px; }')
        layout = QVBoxLayout(self)
        form = QFormLayout()
        form.setContentsMargins(28, 16, 28, 16)
        form.setSpacing(24)
        label_font = QFont('Segoe UI', 14)
        self.name_edit = QLineEdit()
        self.username_edit = QLineEdit()
        self.password_edit = QLineEdit()
        self.link_edit = QLineEdit()
        font = QFont('Segoe UI', 15)
        for w in [self.name_edit, self.username_edit, self.password_edit, self.link_edit]:
            w.setFont(QFont('Segoe UI', 15))
            w.setMinimumHeight(53)
            w.setStyleSheet('''
                QLineEdit {
                    border-radius: 8px;
                    border: 1.5px solid #BDBDBD;
                    padding: 14px 12px 14px 12px;
                    background: #F5F7FA;
                    color: #212121;
                    selection-background-color: #2962FF;
                    font-size: 15pt;
                }
                QLineEdit:focus {
                    border: 1.5px solid #2962FF;
                    box-shadow: 0 0 0 2px #2962FF33;
                }
                QLineEdit::placeholder {
                    color: #9E9E9E;
                    font-style: italic;
                }
            ''')
        self.name_edit.setPlaceholderText('如：百度')
        self.username_edit.setPlaceholderText('如：user@example.com')
        self.password_edit.setPlaceholderText('如：123456')
        self.link_edit.setPlaceholderText('如：https://www.example.com')
        name_label = QLabel('名称:')
        name_label.setFont(label_font)
        name_label.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        username_label = QLabel('账号:')
        username_label.setFont(label_font)
        username_label.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        password_label = QLabel('密码:')
        password_label.setFont(label_font)
        password_label.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        link_label = QLabel('链接:')
        link_label.setFont(label_font)
        link_label.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        form.addRow(name_label, self.name_edit)
        form.addRow(username_label, self.username_edit)
        form.addRow(password_label, self.password_edit)
        form.addRow(link_label, self.link_edit)
        layout.addLayout(form)
        if entry:
            self.name_edit.setText(entry['name'])
            self.username_edit.setText(entry['username'])
            self.password_edit.setText(entry['password'])
            self.link_edit.setText(entry.get('link', ''))
        btn = QPushButton('确定')
        btn.setFont(QFont('Segoe UI Semibold', 14))
        btn.setStyleSheet('QPushButton { border-radius: 18px; background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #2962FF, stop:1 #6200EA); color: white; min-width: 140px; height: 44px; margin-top: 28px; font-size: 15pt; } QPushButton:hover { filter: brightness(0.92); box-shadow: 0 2px 6px rgba(41,98,255,0.3); } QPushButton:pressed { transform: scale(0.95); }')
        btn.clicked.connect(self.accept)
        layout.addWidget(btn, alignment=Qt.AlignHCenter)
        self.name_edit.setFocus()
    def get_data(self):
        return {
            'name': self.name_edit.text().strip(),
            'username': self.username_edit.text().strip(),
            'password': self.password_edit.text().strip(),
            'link': self.link_edit.text().strip()
        }

class PasswordManager(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('本地密码管理器 - PyQt5')
        self.resize(1100, 700)
        self.data = []
        self.visited_links = set()
        self.init_ui()
        self.load_data_plain()

    def load_data_plain(self):
        if not os.path.exists(DATA_FILE):
            self.data = []
        else:
            try:
                with open(DATA_FILE, 'r', encoding='utf-8') as f:
                    self.data = json.load(f)
            except Exception:
                self.data = []
        self.update_table()

    def save_data_plain(self):
        with open(DATA_FILE, 'w', encoding='utf-8') as f:
            json.dump(self.data, f, ensure_ascii=False, indent=2)

    def init_ui(self):
        self.layout = QVBoxLayout(self)
        # 搜索栏
        search_layout = QHBoxLayout()
        self.search_edit = QLineEdit()
        self.search_edit.setPlaceholderText('搜索...')
        self.search_edit.setFont(QFont('Segoe UI', 11))
        self.search_edit.setStyleSheet('QLineEdit { border-radius: 6px; border: 1.5px solid #BDBDBD; padding: 6px; background: #F5F7FA; color: #212121; selection-background-color: #2962FF; } QLineEdit:focus { border: 1.5px solid #2962FF; box-shadow: 0 0 0 2px #2962FF33; } QLineEdit::placeholder { color: #9E9E9E; font-style: italic; }')
        self.search_edit.textChanged.connect(self.update_table)
        search_label = QLabel('搜索:')
        search_label.setFont(QFont('Segoe UI', 11))
        search_layout.addWidget(search_label)
        search_layout.addWidget(self.search_edit)
        self.layout.addLayout(search_layout)
        # 表格
        self.table = QTableWidget(0, 4)
        self.table.setHorizontalHeaderLabels(['名称', '账号', '密码', '链接'])
        self.table.setFont(QFont('Roboto Mono', 12))
        # 设置所有列自适应窗口宽度
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setAlternatingRowColors(True)
        self.table.viewport().installEventFilter(self)
        self.table.cellDoubleClicked.connect(self.cell_double_clicked)
        # 表头玻璃感
        self.table.horizontalHeader().setStyleSheet('QHeaderView::section { background: rgba(245,247,250,0.8); border-bottom: 2px solid #E0E0E0; font-family: Segoe UI Semibold; font-size: 13pt; color: #212121; height: 32px; }')
        # 斑马纹
        self.table.setStyleSheet('QTableWidget { alternate-background-color: #F8FAFE; background: #FFFFFF; gridline-color: #E0E0E0; } QTableWidget::item:selected { background: #E3F2FD; color: #212121; }')
        self.layout.addWidget(self.table)
        # 按钮
        btn_layout = QHBoxLayout()
        self.add_btn = QPushButton('添加')
        self.edit_btn = QPushButton('编辑')
        self.del_btn = QPushButton('删除')
        self.quit_btn = QPushButton('退出')
        for btn, color in zip([self.add_btn, self.edit_btn, self.del_btn, self.quit_btn], ['#2962FF,#6200EA', '#FF6D00,#FF9100', '#D32F2F,#FF6D00', '#757575,#BDBDBD']):
            btn.setFont(QFont('Segoe UI Semibold', 11))
            btn.setFixedHeight(36)
            btn.setStyleSheet(f'''QPushButton {{ border-radius: 18px; background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 {color.split(',')[0]}, stop:1 {color.split(',')[1]}); color: white; min-width: 90px; }} QPushButton:hover {{ filter: brightness(0.92); box-shadow: 0 2px 6px rgba(41,98,255,0.3); }} QPushButton:pressed {{ transform: scale(0.95); }} QPushButton:disabled {{ opacity: 0.35; }}''')
        btn_layout.addWidget(self.add_btn)
        btn_layout.addWidget(self.edit_btn)
        btn_layout.addWidget(self.del_btn)
        btn_layout.addWidget(self.quit_btn)
        self.layout.addLayout(btn_layout)
        self.add_btn.clicked.connect(self.add_entry)
        self.edit_btn.clicked.connect(self.edit_entry)
        self.del_btn.clicked.connect(self.delete_entry)
        self.quit_btn.clicked.connect(self.close)

    def update_table(self):
        keyword = self.search_edit.text().lower()
        self.table.setRowCount(0)
        for idx, entry in enumerate(self.data):
            if (keyword in entry['name'].lower() or
                keyword in entry['username'].lower() or
                keyword in entry.get('link', '').lower()):
                row = self.table.rowCount()
                self.table.insertRow(row)
                # 名称、账号、密码为纯文本
                for col, key in enumerate(['name', 'username', 'password']):
                    item = QTableWidgetItem(entry[key])
                    item.setFont(QFont('Roboto Mono', 12))
                    item.setForeground(QColor('#212121'))
                    self.table.setItem(row, col, item)
                # 链接列
                link = entry.get('link', '')
                link_item = QTableWidgetItem(link)
                font = QFont('Roboto Mono', 12)
                font.setUnderline(bool(link))
                link_item.setFont(font)
                if link:
                    if link in self.visited_links:
                        link_item.setForeground(QColor('#6200EA'))
                    else:
                        link_item.setForeground(QColor('#2962FF'))
                else:
                    link_item.setForeground(QColor('#212121'))
                self.table.setItem(row, 3, link_item)

    def show_toast(self, text):
        # 窗口中心自动消失的提示气泡
        toast = QLabel(text, self)
        toast.setStyleSheet('QLabel { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #2962FF, stop:1 #6200EA); color: white; border-radius: 8px; padding: 10px 24px; font-size: 12pt; box-shadow: 0 2px 8px rgba(41,98,255,0.18); }')
        toast.setWindowFlags(Qt.ToolTip)
        toast.adjustSize()
        geo = self.geometry()
        x = geo.x() + (geo.width() - toast.width()) // 2
        y = geo.y() + (geo.height() - toast.height()) // 2
        toast.move(x, y)
        toast.show()
        QTimer.singleShot(1200, toast.close)

    def cell_double_clicked(self, row, col):
        entry = self.data[row]
        if col == 1:
            QApplication.clipboard().setText(entry['username'])
            self.show_toast('账号已复制到剪贴板！')
        elif col == 2:
            QApplication.clipboard().setText(entry['password'])
            self.show_toast('密码已复制到剪贴板！')
        elif col == 3:
            link = entry.get('link', '')
            if link:
                webbrowser.open(link)
                self.visited_links.add(link)
                self.update_table()
            else:
                QMessageBox.information(self, '提示', '该条目没有链接。')

    def add_entry(self):
        dlg = EntryDialog(self)
        if dlg.exec_():
            new_entry = dlg.get_data()
            if not new_entry['name'] or not new_entry['username'] or not new_entry['password']:
                QMessageBox.warning(self, '提示', '名称、账号、密码不能为空！')
                return
            self.data.append(new_entry)
            self.save_data_plain()
            self.update_table()

    def edit_entry(self):
        row = self.table.currentRow()
        if row < 0:
            QMessageBox.information(self, '提示', '请先选择要编辑的条目。')
            return
        entry = self.data[row]
        dlg = EntryDialog(self, entry)
        if dlg.exec_():
            new_entry = dlg.get_data()
            if not new_entry['name'] or not new_entry['username'] or not new_entry['password']:
                QMessageBox.warning(self, '提示', '名称、账号、密码不能为空！')
                return
            self.data[row] = new_entry
            self.save_data_plain()
            self.update_table()

    def delete_entry(self):
        row = self.table.currentRow()
        if row < 0:
            QMessageBox.information(self, '提示', '请先选择要删除的条目。')
            return
        if QMessageBox.question(self, '确认', '确定要删除该条目吗？') == QMessageBox.Yes:
            self.data.pop(row)
            self.save_data_plain()
            self.update_table()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = PasswordManager()
    win.show()
    sys.exit(app.exec_()) 